require "Common/define"
require "Logic/Config"
require "Common/functions"
require 'View/BattleUI/TeamPartnerInfo'

---@class InvasionHeroInfo
InvasionHeroInfo = Class("InvasionHeroInfo")
--上阵容英雄详情
function InvasionHeroInfo:ctor(param)
    --- @type number 伙伴Id
    self.partnerId = nil;
    --- @type number 伙伴模板Id
    self.partnerModelId = nil;
    --- @type number 伙伴等级
    self.level = nil;
    --- @type number 伙伴星级
    self.star = nil;
    if param then
        self:initData(param);
    end
end

function InvasionHeroInfo:initData(param)
    --- @type number 伙伴Id
    self.partnerId = param.partnerId;
    --- @type number 伙伴模板Id
    self.partnerModelId = param.partnerModelId;
    --- @type number 伙伴等级
    self.level = param.level;
    --- @type number 伙伴星级
    self.star = param.star;
    ---@type number 伙伴职业
    self.type=param.type
end

---@class InvasionManager
InvasionManager = {};
local this = InvasionManager;
InvasionManager.HERO_FORMATION_COUNT = 6;
this.BATTLE_STATE = {
    ADD = 1, --上阵
    DEL = 2, --下阵
}
function InvasionManager.init()
    ---@param showHero table<BattleTeamPartnerInfo>
    this.showHero = {}--上阵英雄列表（布阵页面时）
    ---@param battleHero table<InvasionHeroInfo>
    this.battleHero = {}--上阵英雄列表（布阵页面时）
    this.skillData={}
    this.setInvasionShowHeroFormation({0,0,0,0,0,0})
    this.initRecommendSkillData()
    this.initInvasionReward()

    this.countRemain = 0
    this.highRewardEndTime = 0
    this.rankList = {}
    this.myRank = {}
end
function InvasionManager.initRecommendSkillData()
    local skillTable=G.dataTable["t_collocationskill"]
    local skillShowTable=G.dataTable["t_collocationskillshow"]
    local skillData={}
    for i,v in pairs(skillTable)do
        if v.f_Id>10000 and v.f_Id<20000 and not string.IsNilOrEmpty(v.f_Collocation) then
            v.icon=skillShowTable[ tostring(v.f_Id)].f_SkillIcon
            table.insert(skillData,v)
        end
    end
    table.sort(skillData,function(a,b)
        return a.f_Id<b.f_Id
    end)
    for _,v in ipairs(skillData) do
        local needJobs ={}
        local num=0
        for _,b in ipairs(v.f_Collocation)do
            for i=1,b[2]do
                table.insert(needJobs,b[1])
                num=num+1
            end
        end
        if num~=6 then
            printError("t_collocationSkill"..v.f_Id.."需要职业数错误")
        end
        table.sort(needJobs,function(a, b)
            return a<b
        end)
        v.needJobs= needJobs
    end
    InvasionManager.skillData=skillData
end
function InvasionManager.GetTeamSkillData(skillId)
    local skillTable=G.dataTable["t_collocationskill"]
    local skillShowTable=G.dataTable["t_collocationskillshow"]
    return skillTable[tostring(skillId)]
end
function InvasionManager.GetRecommendSkills()
    --local skills={}
    local heroes = logicMgr.HeroManager.getOwnerHeroList();
    table.sort(heroes,function(a,b)
        if a.type~=b.type then
            return a.type<b.type
        else
            return logicMgr.HeroManager.sortHeroWithPower(a,b)
        end
    end)
    local recommendSkills={}
    for _,skill in ipairs(InvasionManager.skillData)do
        local index=1
        local recommendHeroes={}
        for _,hero in ipairs(heroes)do
            if hero.type==skill.needJobs[index]then
                table.insert(recommendHeroes,hero)
                index=index+1
                if(index>6)then
                    break
                end
            elseif hero.type>skill.needJobs[index] then
                break
            end
        end
        if #recommendHeroes==6 then
            table.insert(recommendSkills,{skill=skill,heroes=recommendHeroes})
        end
    end
    return recommendSkills
end
function InvasionManager.GetCurrentSkill()
    local function IsEqual(a,b)
        local temp=clone(a)
        for i,v in ipairs(b)do
            table.removeByValue(temp,v)
        end
        return table.isNullOrEmpty(temp)
    end
    if this.IsInvasionFull()then
        local jobs={}
        for i,v in ipairs(this.battleHero)do
            table.insert(jobs,v.type)
        end
        for i,v in ipairs(this.GetRecommendSkills())do
            if IsEqual(jobs,v.skill.needJobs)then
                return v
            end
        end
    end
    return nil
end
function InvasionManager.initInvasionReward()
    local rewardTable=G.dataTable["t_collocationreward"]
    InvasionManager.rewardData={}
    local function isEmpty(t)
        if not table.isNullOrEmpty(t)then
            for i,v in pairs(t)do
                if not table.isNullOrEmpty(v) then
                    return false
                end
            end
        end
        return true
    end
    for i,v in pairs(rewardTable)do
        if not (isEmpty(v.f_CollocationReward))then
            table.insert(InvasionManager.rewardData,v)
        end
    end
    table.sort(InvasionManager.rewardData,function(a, b)
        return toNumber(a.f_CollocationId) <toNumber( b.f_CollocationId)
    end)
end
function InvasionManager.getInvasionRewards(level1,level2)
    if level1 ==nil and level2==nil then
        return InvasionManager.rewardData
    end
    local rewards={}
    level1=level1 or -1
    level2=level2 or Mathf.Infinity
    for i,v in ipairs(InvasionManager.rewardData)do
        if toNumber(v.f_CollocationId)> level1 and toNumber(v.f_CollocationId)<=level2 then
            table.insert(rewards,v)
        end
    end
    return rewards
end
--------------------------布阵 START------------------------------
--获取可使用英雄数据
function InvasionManager.getInvasionHeroes()
    this.showHero = {};
    local data = logicMgr.HeroManager.getOwnerHeroList();
    for i = 1, #data do
        local hero = BattleTeamPartnerInfo.New(1);
        hero:setInfo(data[i]);
        table.insert(this.showHero, hero)
    end
    return this.showHero;
end
--上下阵英雄 传入id 返回是上阵还是下阵
function InvasionManager.setInvasionShowHeroState(id)
    local idxAdd = this.getInvasionShowHeroFormationIdx();
    local idxDel = this.checkInvasionShowHeroFormationToId(id);
    if idxDel ~= 0 then
        --下阵
        this.battleHero[idxDel]:initData({});
        return this.BATTLE_STATE.DEL;
    else
        if idxAdd == 0 then
            --上阵人数满了
            UISysTips.AddMsg(getLanguage("Character_Tips1"));
            return ;
        else
            --上阵
            local heroData = HeroManager.getHeroDatabyModelId(id)
            this.battleHero[idxAdd]:initData(heroData);
            return this.BATTLE_STATE.ADD;
        end
    end
end
--下阵对应位置英雄
function InvasionManager.SetHeroDown(index)
    this.battleHero[index]:initData({});
end
--设置上阵英雄的阵容
function InvasionManager.setInvasionShowHeroFormation(formation)
    this.battleHero = {}
    for i = 1, this.HERO_FORMATION_COUNT do
        local heroData = logicMgr.HeroManager.getHeroDatabyPartnerId(formation[i])
        local item = InvasionHeroInfo:New()
        if heroData then
            item:initData(heroData);
        end
        table.insert(this.battleHero, item);
    end
end
--检查英雄 返回传入id的索引 否则返回空位的索引  否则返回0
function InvasionManager.checkInvasionShowHeroFormationToId(id)
    id =tonumber(id)
    for i = 1, this.HERO_FORMATION_COUNT do
        local hero = this.battleHero[i];
        if tonumber(hero.partnerModelId)  == id then
            return i;
        end
    end
    return 0;
end
--获取可上阵的idx 若无可上阵位置则返回0
function InvasionManager.getInvasionShowHeroFormationIdx()
    for i = 1, this.HERO_FORMATION_COUNT do
        local hero = this.battleHero[i];
        if hero.partnerId == nil then
            return i;
        end
    end
    return 0;
end
--获取上阵队伍信息
function InvasionManager.getInvasionBattleFormation()
    return clone(this.battleHero);
end
--下阵所有英雄
function InvasionManager.clearInvasionBattleHero()
    for i=1,InvasionManager.HERO_FORMATION_COUNT do
        this.battleHero[i]:initData({});
    end
end
--上阵所有英雄
function InvasionManager.setAllInvasionBattleHero(heroes)
    for i=1,InvasionManager.HERO_FORMATION_COUNT do
        this.battleHero[i]:initData(heroes[i]);
    end
end
--获取上阵英雄数量
function InvasionManager.IsInvasionFull()
    local num=0
    for i=1,InvasionManager.HERO_FORMATION_COUNT do
        if this.battleHero[i].partnerId~=nil then
            num=num+1
        end
    end
    return num==InvasionManager.HERO_FORMATION_COUNT
end

function InvasionManager.setSkillBtn2(skillBtn,data)
    local icon=skillBtn:GetChild("Mask"):GetChild("Icon")
    local stateCtrl= skillBtn:GetController("state")

    if not table.isNullOrEmpty(data)then
        icon.url="ui://SkillAtlas/"..data.icon
        stateCtrl.selectedIndex=1
    else
        stateCtrl.selectedIndex=0
    end
end
function InvasionManager.SendWorldInvitation(level)
    local text=string.format( getLanguage("InvasionChat"),level,Config.ChatLinkType.InvasionInvite)
    local curChannel=Config.MsgChannel.World
    local msgtbl = {};
    msgtbl.Channel = curChannel;
    msgtbl.Message = text
    msgtbl.serverId = Config.chatServerId
    msgtbl.head = logicMgr.HeroManager.GetRoleHeadID();
    msgtbl.headFrame = logicMgr.HeroManager.GetRoleHeadFrame()
    local tempList = logicMgr.TitleManager.GetTitleData().showList
    msgtbl.titleId = tempList and tempList[1] or 0;
    msgtbl.level = logicMgr.HeroManager.GetRoleLevel();
    msgtbl.roleId = logicMgr.HeroManager.GetRoleId();
    msgtbl.roleName = logicMgr.HeroManager.GetRoleName();
    msgtbl.unRead = true;
    msgtbl.time = HelperFunc.GetServerTime(false);
    msgtbl.lbs = logicMgr.LBSManager.GetLocationName()
    msgtbl.unionName = logicMgr.GuildManager.getUnionName();

    if IsWindowEditor() then
        --chatHandler.broadCastMsg(chatHandler.mychatChannel[curChannel], msgtbl);
        chatHandler.onRecChatMsg(msgtbl)
    else
        logicMgr.SDKManager.SendTextMessageByWorld(text)
    end
    chatHandler.ReqChatInfo(1, text)
end

function InvasionManager.addChatMsg(message)
    if isOpenUI(PanelNames.UIBulletChat) then
        local ui_bullet_chat = CtrlManager.GetCtrl(PanelNames.UIBulletChat)
        if ui_bullet_chat ~= nil then
            message= EmojiParser.inst:Parse(message);
            ui_bullet_chat.PlayNetStoryComment({message},true)
        end
    end
end
function InvasionManager.GetServerOpenDelta(day,hour)
    if day<1 then
        printError("开服天数不能小于1")
    end
    local serverOpenTime=ConvertCSharpLongNumber(logicMgr.LoginManager.GetServerOpenTime())/1000
    local temp = os.date("*t", math.floor(serverOpenTime));
    temp = os.time({year = temp.year, month = temp.month, day = temp.day, hour = 0, min = 0, sec = 0});
    local num = temp+ (day-1)*3600 * 24+hour*3600
    return num
end

function InvasionManager.IsOpen()
    --return true
    local openTime = tonumber(logicMgr.CronMgr.GetNextDateTime(dataTable.getGlobalString(655),HelperFunc.GetServerTime()))
    local endTime = tonumber(logicMgr.CronMgr.GetNextDateTime(dataTable.getGlobalString(654),HelperFunc.GetServerTime()))
    local time =  HelperFunc.GetServerTime()

    if time >= openTime and time < endTime then
        return true
    end
    if openTime > endTime and time < endTime then
        return true
    end
    return false
end
function InvasionManager.QuitBattle()
    local function Close(name)
        if isOpenUI(name)then
            closeUI(name)
        end
    end
    local names ={
        PanelNames.UIInvasionBattle,
        PanelNames.UIInvasionTeam,
        PanelNames.UIInvasionTeamList,
        PanelNames.UITeamSetting,
        PanelNames.UITeamApply,
        PanelNames.UITeamRecommend,
        PanelNames.UITeamSkillDetails,
        PanelNames.UIInvasionHookReward,
        PanelNames.UIInvasionDropPreview,
    }
    for i,v in ipairs(names)do
        Close(v)
    end
end
function InvasionManager.SetInvasionKicked(state)
    SetPlayerPrefs("InvasionKicked",state)
    FireEvent(Config.EventType.InvasionKickedUpdate)
end
function InvasionManager.IsInvasionKicked()
    local num=GetPlayerPrefs("InvasionKicked")
    if num~=nil then
        if tonumber(num)==1 then
            return true
        end
    end
    return false
end
--[[function InvasionManager.SetInvasionFirstOpen(state)
    if state==0 then
        SetPlayerPrefs("InvasionFirstOpen",0)
        FireEvent(Config.EventType.InvasionFirstOpen)
        return
    end
    local openTime = tonumber(logicMgr.CronMgr.GetNextDateTime(dataTable.getGlobalString(412),HelperFunc.GetServerTime()))
    local endTime = tonumber(logicMgr.CronMgr.GetNextDateTime(dataTable.getGlobalString(410),HelperFunc.GetServerTime()))
    local time =  HelperFunc.GetServerTime()
    local flag=false
    if time >= openTime and time < endTime then
        flag=true
    end
    if openTime > endTime and time < endTime then
       flag=true
    end
    if flag then
        local saveEnd=GetPlayerPrefs("InvasionEndTime")
        if (saveEnd==nil or tonumber(saveEnd)~=tonumber(endTime))then
            SetPlayerPrefs("InvasionEndTime",endTime)
            SetPlayerPrefs("InvasionFirstOpen",1)
            FireEvent(Config.EventType.InvasionFirstOpen)
        end
        return true
    end
end]]
function InvasionManager.IsInvasionFirstOpen()
    local firstOpen=GetPlayerPrefs("InvasionFirstOpen")
     if firstOpen == "1" then
        return false
    end
    return true
end

function InvasionManager.SetInvasionHighRewardInfo(data)
    this.countRemain = data.countRemain or 0
    this.highRewardEndTime = tonumber(tostring(data.timeRemain))*0.001 or 0
end

function InvasionManager.GetInvasionHighRewardInfo()
    return this.countRemain,this.highRewardEndTime
end

function InvasionManager.SetInvasionRank(data)
    this.rankList = data.rankList or {}
    this.myRank = data.myInfo or {}
end

function InvasionManager.GetInvasionRank()
    return this.rankList,this.myRank
end

return InvasionManager
